package cn.edu.cqvie.video;

import cn.edu.cqvie.video.bean.MediaInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import okhttp3.*;
import org.jsoup.Jsoup;

import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class DouYinQushuiyin {

    private static Lock lock = new ReentrantLock();
    private static int nThread = Runtime.getRuntime().availableProcessors();
    private static ExecutorService execute = new ThreadPoolExecutor(nThread, nThread * 2,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(32),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws Throwable {

        //uploadDemo();

        uploadParallel();
    }

    /**
     * 并行上传
     */
    public static void uploadParallel() {
        for (int i = 0; i < 2; i++) {
            execute.submit(() -> {
                try {
                    collect();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            });
        }
    }

    /**
     * 上传demo
     *
     * @throws Throwable
     */
    public static void uploadDemo() throws Throwable {
        //网络地址
        String networkUrl = "https://api.amemv.com/aweme/v1/play/?video_id=v0300fc10000bki6597n07ovfudv49gg&line=1&ratio=540p&media_type=4&vr_type=0&improve_bitrate=0&is_play_url=1";

        //本地地址
        InputStream inputStream = downloadStream(networkUrl);

        //oss地址
        String ossUrl = upload(inputStream);
    }

    /**
     * 业务聚合
     *
     * @throws IOException
     */
    public static void collect() throws Throwable {
        //查询列表
        List<MediaInfo> list = select();
        if (list == null || list.size() == 0) {
            return;
        }

        list.stream().forEach(item -> {
            try {
                //网络地址
                String networkUrl = item.getOpenUrls();

                //本地地址
                InputStream inputStream = downloadStream(networkUrl);

                //oss地址
                String ossUrl = upload(inputStream);

                //更新数据
                item.setOpenUrls(ossUrl);
                update(item);

            } catch (Throwable e) {
                e.printStackTrace();
            }
        });
        //递归
        collect();
    }


    public static String update(MediaInfo mediaInfo) throws IOException {
        String url = "http://api.xiamiservice.com/api/reptile/media/info/update";
        String str = post(url, JSON.toJSONString(mediaInfo));
        System.out.println("\n-----视频更新返回-----\n" + str);
        return str;
    }

    public static List<MediaInfo> select() throws IOException {
        List<MediaInfo> list = new ArrayList<MediaInfo>();
        if (lock.tryLock()) {
            try {

                String url = "http://api.xiamiservice.com/api/reptile/media/info/selectPage";
                String str = post(url, "{}");

                JSONObject result = JSONObject.parseObject(str);
                JSONObject data = JSONObject.parseObject(result.get("data").toString());
                list = JSONObject.parseArray(data.getString("list"), MediaInfo.class);
                System.out.println("\n-----视频接口返回-----\n" + list.toString());

            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                lock.unlock();
            }
        } else {

            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            select();
        }
        return list;
    }

    /**
     * POST 请求
     *
     * @param url  地址
     * @param data JSON格式的数据字符串
     * @return
     * @throws IOException
     */
    public static String post(String url, String data) throws IOException {
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, data);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .addHeader("deviceid", "mac-vs")
                .addHeader("content-type", "application/json")
                .addHeader("cache-control", "no-cache")
                .addHeader("postman-token", "b186f6ce-98a5-0ff7-4df5-a07cd8d3c2a4")
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * 下载视频
     *
     * @param matchUrl
     * @return
     * @throws IOException
     */
    public static String download(String matchUrl) throws IOException {
        BufferedInputStream in = new BufferedInputStream(downloadStream(matchUrl));

        Long timetmp = System.currentTimeMillis();
        String fileAddress = "d:/抖音视频/douyin_" + timetmp + ".mp4";

        //7.封装一个保存文件的路径对象
        File fileSavePath = new File(fileAddress);

        //注:如果保存文件夹不存在,那么则创建该文件夹
        File fileParent = fileSavePath.getParentFile();
        if (!fileParent.exists()) {
            fileParent.mkdirs();
        }

        //8.新建一个输出流对象
        OutputStream out =
                new BufferedOutputStream(
                        new FileOutputStream(fileSavePath));

        //9.遍历输出文件
        int b;
        while ((b = in.read()) != -1) {
            out.write(b);
        }

        out.close();//关闭输出流
        in.close(); //关闭输入流

        //注:打印获取的链接
        System.out.println("-----抖音去水印链接-----\n" + matchUrl);
        System.out.println("\n-----视频保存路径-----\n" + fileSavePath.getAbsolutePath());
        return fileAddress;
    }

    public static InputStream downloadStream(String matchUrl) throws IOException {
        //5.将链接封装成流
        //注:由于抖音对请求头有限制,只能设置一个伪装手机浏览器请求头才可实现去水印下载
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Connection", "keep-alive");
        headers.put("Host", "aweme.snssdk.com");
        headers.put("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1");

        //6.利用Joup获取视频对象,并作封装成一个输入流对象
        byte[] bytes = Jsoup.connect(matchUrl).headers(headers).timeout(10000).ignoreContentType(true).execute().bodyAsBytes();
        return new ByteArrayInputStream(bytes);
    }

    /**
     * 上传OSS
     *
     * @param inputStream
     * @return
     */
    public static String upload(InputStream inputStream) throws Throwable {
        String endpoint = "oss-cn-zhangjiakou.aliyuncs.com";
        String accessKeyId = "LTAInu0vtx4LOWZR";
        String secretAccessKey = "xu3irS0ehSJubz7Wa8edeA9x5gyaxQ";
        String fileType = "mp4";
        String id = String.valueOf(System.currentTimeMillis());

        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, secretAccessKey);
        String filePath = fileType + File.separator + id + "." + fileType;
        ossClient.putObject("ixm", filePath, inputStream);
        String ossUrl = "https://ixm." + endpoint + "/" + filePath;
        System.out.println("\n-----抖音OSS链接-----\n" + ossUrl);
        return ossUrl;
    }

    /**
     * 上传OSS
     *
     * @param localUrl
     * @return
     */
    public static String upload(String localUrl) throws Throwable {
        String endpoint = "oss-cn-zhangjiakou.aliyuncs.com";
        String accessKeyId = "LTAInu0vtx4LOWZR";
        String secretAccessKey = "xu3irS0ehSJubz7Wa8edeA9x5gyaxQ";
        String fileType = "mp4";
        String id = String.valueOf(System.currentTimeMillis());

        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, secretAccessKey);
        String filePath = fileType + File.separator + id + "." + fileType;
        ossClient.putObject("ixm", filePath, new FileInputStream(new File(localUrl)));
        String ossUrl = "https://ixm." + endpoint + "/" + filePath;
        System.out.println("\n-----抖音OSS链接-----\n" + ossUrl);
        return ossUrl;
    }

    /**
     * 分享地址获取视频地址
     *
     * @return
     * @throws IOException
     */
    private static String getUrl() throws IOException {
        //●抖音链接(使用手机分享功能,复制链接)
        String url = "http://v.douyin.com/2MKBC6/";

        String url1 = "#在抖音，记录美好生活#好好看 http://v.douyin.com/6xrJQP/ 复制此链接，打开【抖音短视频】，直接观看视频！";


        //过滤链接，获取http连接地址
        String finalUrl = decodeHttpUrl(url1);

        //1.利用Jsoup抓取抖音链接
        //抓取抖音网页
        String htmls = Jsoup.connect(finalUrl).ignoreContentType(true).execute().body();
        System.out.println(htmls); //做测试时使用

        //2.利用正则匹配可以抖音下载链接
        //playAddr: "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200ffc0000bfil6o4mavffbmroeo80&line=0",
        //具体匹配内容格式：「https://aweme.snssdk.com/aweme/...line=0」
        Pattern patternCompile = Pattern.compile("(?<=playAddr: \")https?://.+(?=\",)");
        //利用Pattern.compile("正则条件").matcher("匹配的字符串对象")方法可以将需要匹配的字段进行匹配封装 返回一个封装了匹配的字符串Matcher对象

        //3.匹配后封装成Matcher对象
        Matcher m = patternCompile.matcher(htmls);

        //4.①利用Matcher中的group方法获取匹配的特定字符串 ②利用String的replace方法替换特定字符,得到抖音的去水印链接
        String matchUrl = "";
        while (m.find()) {
            matchUrl = m.group(0).replaceAll("playwm", "play");
        }
        return matchUrl;
    }

    public static String decodeHttpUrl(String url) {
        int start = url.indexOf("http");
        int end = url.lastIndexOf("/");
        String decodeurl = url.substring(start, end);
        return decodeurl;
    }
}